﻿Function.createSynchronizer = function Function$createSynchronizer(instance, method) {
	/// <summary locid="M:J#Function.createDelegate" />
	/// <param name="instance" mayBeNull="true"></param>
	/// <param name="method" type="Function"></param>
	/// <returns type="Function"></returns>
	var e = Function._validateParams(arguments, [
		{ name: "instance", mayBeNull: true },
		{ name: "method", type: Function }
	]);
	if (e) throw e;

	return function() {
		var length = arguments.length;
		var args = [];
		//args[length] = instance;

		if (length > 0)
			for (var index = 0; index < length; index++)
			args[index] = arguments[index];

		var onTimeout = function() {
			method.apply(instance, args);
		}

		window.setTimeout(onTimeout, 0);
	}
}

Function.lock = function(instance) {
	//var e = Function._validateParams(arguments, [
	//	{ name: "instance", type: Object, mayBeNull: false }
	//]);
	//if (e) throw e;

	if (instance["_queue"] == null)
		instance["_queue"] = new Array();

	var queue = instance["_queue"];
	queue.push(arguments.caller);
}

Function.prototype.wait = function(millis, scope) {
	var args = [];
	var length = arguments.length;
	if (length > 2)
		args = Array.prototype.slice.call(arguments, 2);

	var method = this;
	var fn = function() {
		var result = method.apply(scope, args);
		method._timer_id = null;
		return result;
	}

	if (millis) {
		method._timer_id = window.setTimeout(fn, millis);
		return;
	}

	method();
}

Function.prototype.stop = function() {
	if (this._timer_id) {
		window.clearTimeout(this._timer_id);
		this._timer_id = null;
	}
}


Function.prototype.isBusy = function() {
	return (this._timer_id != null);
}

Function.unlock = function(instance) {
	//var e = Function._validateParams(arguments, [
	//	{ name: "instance", type: Object, mayBeNull: false }
	//]);
	//if (e) throw e;

	if (instance["_queue"] == null)
		return;

	var queue = instance["_queue"]
	var method = null;
	while (method = queue.shift()) {
		method.callee.apply(instance, method);
	}
}

Function.eventWraper = function(instance, method) {
	return function(event) {
		return method.apply(instance, [event, this]);
	}
}

function apply(object1, object2) {
	if (object1 == null)
		object1 = new Object();

	if (object2 == null)
		return object1;
		
	for (var property in object2) {
		object1[property] = object2[property];
	}

	return object1;
}